<template>
  <div class="zm-time-picker">
    <input
      ref="inputRef"
      type="text"
      id="zm-input-0208"
      class="input"
      :class="{ focus: isFocus, disabled: disabled }"
      readonly
      :placeholder="placeholder"
      :value="displayValue"
      :disabled="disabled"
      @input="$emit('input', [$event.target.value, stopDisplayValue])"
      @focus="handleFocus"
      @blur="handleBlur"
      @mouseenter="hanleMouseenter"
      @mouseleave="showCloseIcon = false"
    />
    <i style="font-style: normal;">至</i>
    <input
      ref="inputRef"
      id="zm-input-0208"
      type="text"
      class="input"
      :class="{ focus: isFocus, disabled: disabled }"
      readonly
      :placeholder="placeholder"
      :value="stopDisplayValue"
      :disabled="disabled"
      @input="$emit('input', [displayValue, $event.target.value])"
      @focus="handleFocus"
      @blur="handleBlur"
      @mouseenter="hanleMouseenter"
      @mouseleave="showCloseIcon = false"
    />

    <!-- 一键清空图标 -->
    <!-- <span
            v-if="clearable"
            @mouseenter="hanleMouseenter"
            @mouseleave="showCloseIcon = false"
            @click="hanldeCloseIconClick"
            slot="suffix"
            class="input-suffix">
            <i v-if="showCloseIcon" class="el-icon-circle-close"></i>
        </span> -->

    <!-- 选择面板 -->
    <div
      v-if="showPanel"
      @click="panelClick"
      id="zm-panel-0208"
      class="time-panel"
    >
      <div class="pleneBox">
        <div class="time-panel1">
          <div class="title">开始时间</div>
          <div class="time-panel-content">
            <!-- 小时列表 -->
            <ul
              ref="housListRef"
              @scroll.stop="bindHoursScroll"
              class="time-spinner-list"
            >
              <li
                @mousedown="choseHour(index, $event)"
                class="time-spinner-list-item"
                :class="{ active: index === hoursActiveIndex }"
                v-for="(h, index) in getHoursList"
                :key="index"
              >
                {{ h > 9 ? h : "0" + h }}
              </li>
            </ul>

            <!-- 分钟列表 -->
            <ul
              ref="minutesListRef"
              @scroll.stop="bindMinutesScroll"
              class="time-spinner-list"
            >
              <li
                @mousedown="choseMinute(index, $event)"
                class="time-spinner-list-item"
                :class="{ active: index === minutesActiveIndex }"
                v-for="(m, index) in getMinutesList"
                :key="index"
              >
                {{ m > 9 ? m : "0" + m }}
              </li>
            </ul>

            <!-- 当前选中范围标记 -->
            <div class="active-flag"></div>
          </div>
        </div>
        <div class="time-panel1">
          <div class="title">结束时间</div>
          <div class="time-panel-content">
            <!-- 小时列表 -->
            <ul
              ref="stopHousListRef"
              @scroll.stop="stopBindHoursScroll"
              class="time-spinner-list"
            >
              <li
                @mousedown="stopChoseHour(index, $event)"
                class="time-spinner-list-item"
                :class="{ active: index === stopHoursActiveIndex }"
                v-for="(h, index) in getHoursList"
                :key="index"
              >
                {{ h > 9 ? h : "0" + h }}
              </li>
            </ul>

            <!-- 分钟列表 -->
            <ul
              ref="stopMinutesListRef"
              @scroll.stop="stopDMinutesScroll"
              class="time-spinner-list"
            >
              <li
                @mousedown="stopChoseMinute(index, $event)"
                class="time-spinner-list-item"
                :class="{ active: index === stopMinutesActiveIndex }"
                v-for="(m, index) in getMinutesList"
                :key="index"
              >
                {{ m > 9 ? m : "0" + m }}
              </li>
            </ul>

            <!-- 当前选中范围标记 -->
            <div class="active-flag"></div>
          </div>
        </div>
      </div>

      <!-- 底部按钮 -->
      <!-- <div class="time-panel-footer">
        <div @mousedown="cancelBtnClick" class="cancel-btn">Cancel</div>
      </div> -->
    </div>
  </div>
</template>

<script>
import { getDateTime } from "@/utils/ruoyi";
export default {
  name: "TimePicker",
  props: {
    value: Array, // v-model 日期对象 | 时间戳
    placeholder: {
      type: Array,
      default: ()=>[],
    },

    defaultValue: {
      // 默认显示时间
      default() {
        return ["2023/01/01 00:00:00", "2023/01/01 00:00:00"];
      },
    },
    minutesStep: {
      // 设置分钟跨度
      validator: function (value) {
        return typeof value === "number" && value > 0;
      },
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    clearable: {
      type: Boolean,
      default: true,
    },
  },
  mounted() {
    document.addEventListener("click", this.hidePanel);
  },
  beforeDestroy() {
    document.removeEventListener("click", this.hidePanel);
  },
  data() {
    return {
      showCloseIcon: false,
      showPanel: false,
      timer: null,
      hoursActiveIndex: 0,
      minutesActiveIndex: 0,
      stopHoursActiveIndex: 0,
      stopMinutesActiveIndex: 0,

      isFocus: false,
      oldVal: null, // 记录value, 用于cancel还原
    };
  },
  computed: {
    valueIsEmpty() {
      const val = this.value && this.value?.length;
      if (val) {
        return false;
      }
      return true;
    },
    // 输入框内展示的值-开始时间
    displayValue() {
      let val = "";
      if (this.value && this.value?.length) {
        val = this.value[0];
      }
      if (val) {
        const date = new Date(val);
        let hours = date.getHours();
        let minutes = date.getMinutes();
        hours = hours > 9 ? hours : "0" + hours;
        minutes = minutes > 9 ? minutes : "0" + minutes;
        return hours + ":" + minutes;
      }
      return "";
    },
    //  输入框内展示的值-结束时间
    stopDisplayValue() {
      let val = "";
      if (this.value && this.value?.length) {
        val = this.value[1];
      }
      if (val) {
        const date = new Date(val);
        let hours = date.getHours();
        let minutes = date.getMinutes();
        hours = hours > 9 ? hours : "0" + hours;
        minutes = minutes > 9 ? minutes : "0" + minutes;
        return hours + ":" + minutes;
      }
      return "";
    },
    // 分钟列表
    getMinutesList() {
      const res = [];
      for (let i = 0; i < 60; i++) {
        if (this.minutesStep) {
          if (i % this.minutesStep === 0) res.push(i);
        } else {
          res.push(i);
        }
      }
      return res;
    },
    // 小时列表
    getHoursList() {
      const res = [];
      for (let i = 0; i < 24; i++) {
        res.push(i);
      }
      return res;
    },
  },
  methods: {
    // 更新面板中时间所在位置
    updatePosition() {
      const hoursMenuEl = this.$refs.housListRef;
      const minutesMenuEl = this.$refs.minutesListRef;
      const stopHoursMenuEl = this.$refs.stopHousListRef;
      const stopMinutesMenuEl = this.$refs.stopMinutesListRef;
      const value = this.value || this.defaultValue;
      const date = new Date(value[0]);
      const date2 = new Date(value[1]);
      const h = date.getHours();
      const m = date.getMinutes();
      const h2 = date2.getHours();
      const m2 = date2.getMinutes();
      this.stopHoursActiveIndex = this.getHoursList.indexOf(h2);
      this.stopMinutesActiveIndex = this.getMinutesList.indexOf(m2);
      this.minutesActiveIndex = this.getMinutesList.indexOf(m);
      this.hoursActiveIndex = this.getHoursList.indexOf(h);

      hoursMenuEl.scrollTo({
        top: this.hoursActiveIndex * 32,
      });

      minutesMenuEl.scrollTo({
        top: this.minutesActiveIndex * 32,
      });

      stopHoursMenuEl.scrollTo({
        top: this.stopHoursActiveIndex * 32,
      });

      stopMinutesMenuEl.scrollTo({
        top: this.stopMinutesActiveIndex * 32,
      });
    },
    // 隐藏面板
    hidePanel(e) {
      const id = e.target.id || "";
      const targetIdList = ["zm-input-0208", "zm-panel-0208"];

      if (targetIdList.indexOf(id) === -1) {
        this.showPanel = false;
        this.isFocus = false;
      }
    },
    panelClick(e) {
      e.stopPropagation(); // 阻止冒泡 点击面板不消失
      this.$refs.inputRef.focus(); // 点击面板时，input输入框默认失焦，手动聚焦，保证下一次点击触发input的blur事件
    },
    handleFocus(e) {
      this.showPanel = true;
      this.isFocus = true;
      // value为空，聚焦显示默认时间
      if (!this.value || !this.value.length) {
        this.$emit("input", this.defaultValue);
      }
    
      // 记录当前值
      this.oldVal = this.value;

      this.$nextTick(() => {
        this.updatePosition();
      });
    },
    handleBlur(e) {
      // this.showPanel = false
      this.isFocus = false;

      // 值无变动，不触发事件
      if (this.value === this.oldVal) return;

      this.$emit("change");
    },
    hanleMouseenter() {
      // 有值才显示一键清空icon
      if (!this.valueIsEmpty) {
        this.showCloseIcon = true;
      }
    },
    hanldeCloseIconClick() {
      this.showCloseIcon = false;
      this.$emit("input", "");
    },
    // 选择小时
    choseHour(index, e) {
      const parent = e.target.parentElement;
      // 滚动到中心点
      parent.scrollTo({
        top: index * 32,
        behavior: "smooth",
      });

      const h = this.getHoursList[index];
      let startDate = new Date(this.value[0]).setHours(h);
      let endDate = new Date(this.value[1])

      this.$emit("input", [startDate, endDate]);
    },

    stopChoseHour(index, e) {
      const parent = e.target.parentElement;

      // 滚动到中心点
      parent.scrollTo({
        top: index * 32,
        behavior: "smooth",
      });

      const h = this.getHoursList[index];
      const startDate = new Date(this.value[0]);
      const endDate = new Date(this.value[1]).setHours(h);
      this.$emit("input", [startDate, endDate]);
    },

    choseMinute(index, e) {
      const parent = e.target.parentElement;
      parent.scrollTo({
        top: index * 32,
        behavior: "smooth",
      });
      const m = this.getMinutesList[index];
      const startDate = new Date(this.value[0]).setMinutes(m);
      const endDate = new Date(this.value[1])
      this.$emit("input", [startDate, endDate]);
    },
    stopChoseMinute(index, e) {
      const parent = e.target.parentElement;
      parent.scrollTo({
        top: index * 32,
        behavior: "smooth",
      });
      const m = this.getMinutesList[index];
      const startDate = new Date(this.value[0]);
      const endDate = new Date(this.value[1]).setMinutes(m);
      this.$emit("input", [startDate, endDate]);
    },

    // 监听小时列表滚动
    bindHoursScroll(e) {
      this.bindScroll(e.target, "hours");
    },
    stopBindHoursScroll(e) {
      this.bindScroll(e.target, "stopHours");
    },
    // 监听分钟列表滚动
    bindMinutesScroll(e) {
      this.bindScroll(e.target, "minutes");
    },

    stopDMinutesScroll(e) {
      this.bindScroll(e.target, "stopMinutes");
    },
    bindScroll(el, type) {
      // 每一个li写死的高度为32px 判断（scrollTop/32）得到的 index 就是几个li的高度
      const scrollTop = el.scrollTop;
      const index = Math.round(scrollTop / 32);

      if (this.timer) {
        clearTimeout(this.timer);
      }

      this.timer = setTimeout(() => {
        el.scrollTo({
          top: index * 32,
          behavior: "smooth",
        });

        if (type === "hours") {
          this.hoursActiveIndex = index;

          const h = this.getHoursList[index];
          const startDate = new Date(this.value[0]).setHours(h);
          const endDate = new Date(this.value[1]);
          this.$emit("input", [startDate, endDate]);
        }

        if (type === "minutes") {
          this.minutesActiveIndex = index;

          const h = this.getMinutesList[index];
          const startDate = new Date(this.value[0]).setMinutes(h);
          const endDate = new Date(this.value[1]);
          this.$emit("input", [startDate, endDate]);
        }
        if (type === "stopHours") {
          this.stopHoursActiveIndex = index;

          const m = this.getHoursList[index];
          const startDate = new Date(this.value[0]);
          const endDate = new Date(this.value[1]).setHours(m);
          this.$emit("input", [startDate, endDate]);
        }
        if (type === "stopMinutes") {
          this.stopMinutesActiveIndex = index;

          const h = this.getMinutesList[index];
          const startDate = new Date(this.value[0]);
          const endDate = new Date(this.value[1]).setMinutes(h);
          this.$emit("input", [startDate, endDate]);
        }
      }, 200);
    },
    cancelBtnClick() {
      this.showPanel = false;
      this.isFocus = false;
      this.$emit("input", this.oldVal);
    },
  },
};
</script>

<style lang="scss" scoped>
.zm-time-picker {
  position: relative;
  display: flex;
  align-items: center;
  border: 1px solid #dcdfe6;
  height: 32px;

  .input {
    box-sizing: border-box;
    width: 44%;
    height: 30px;
    padding: 0 30px;
    border-radius: 4px;
    border: none;
    color: #606266;
    font-weight: inherit;
    font-size: 14px;
    transition: border-color 0.2s;
    outline: none;
  }

  .input::placeholder {
    opacity: 0.5;
  }

  .input:hover {
    border-color: #c0c4cc;
  }

  .input:focus {
    border-color: #409eff;
  }

  .focus {
    border-color: #409eff;
  }

  .disabled {
    background: #f5f7fa;
    color: #c0c4cc;
    opacity: 1;
  }

  .input-prefix,
  .input-suffix {
    display: flex;
    justify-content: center;
    align-items: center;
    color: #c0c4cc;
    height: 100%;
    width: 25px;
    font-size: 14px;
    // line-height: 34px;
    text-align: center;
  }

  .input-prefix {
    position: absolute;
    top: 0;
    left: 5px;
  }

  .input-suffix {
    position: absolute;
    top: 0;
    right: 5px;
    cursor: pointer;
  }

  .time-panel {
    position: absolute;
    top: 40px;
    padding: 7px;
    width: 100%;
    border: 1px solid #e4e7ed;
    border-radius: 2px;
    box-shadow: 0 0 10px #ddd;
    user-select: none;
    background: #fff;
    z-index: 999;

    .pleneBox {
      width: 100%;
      display: flex;

      .time-panel1 {
        width: 50%;
      }
    }

    .title {
      display: flex;
      justify-content: center;
      font-size: 12px;
    }

    .time-panel-content {
      margin-top: px;
      margin-left: 5px;

      border: 1px solid #dcdfe6;
      position: relative;
      display: flex;
      // width: 50%;
      height: 180px;

      .active-flag {
        position: absolute;
        top: 80px;
        // left: 50%;
        // transform: translate(-50%);
        height: 31px;
        width: calc(100% - 8px);
        border-top: 1px solid #ddd;
        border-bottom: 1px solid #ddd;
        pointer-events: none;
      }

      .time-spinner-list {
        height: 100%;
        width: 50%;
        padding: 0;
        margin: 0;
        list-style: none;
        overflow-y: auto;

        .time-spinner-list-item {
          height: 32px;
          font-size: 12px;
          // color: #606266;
          text-align: center;
          font-weight: 400;
          line-height: 32px;

          &:hover {
            background-color: #f5f7fa;
          }

          &.active {
            color: #222222;
            font-weight: bold;
          }

          &.active:hover {
            background-color: #ffffff;
          }
        }

        &::before {
          content: "";
          display: block;
          height: 80px;
        }

        &::after {
          content: "";
          display: block;
          height: 80px;
        }

        &::-webkit-scrollbar {
          width: 6px;
          opacity: 0;
          background-color: rgba(0, 0, 0, 0);
        }

        &::-webkit-scrollbar-thumb {
          background-color: rgba(0, 0, 0, 0);
          opacity: 0;
        }

        &::-webkit-scrollbar-track {
          border-radius: 10px;
          background-color: rgba(255, 255, 255, 0.5); //设置背景透明
        }

        &:hover::-webkit-scrollbar {
          opacity: 1;
        }

        &:hover::-webkit-scrollbar-thumb {
          background: #ddd;
          border-radius: 2px;
          opacity: 1;
        }
      }
    }

    .time-panel-footer {
      box-sizing: border-box;
      border-top: 1px solid #e4e4e4;
      padding: 4px;
      height: 36px;
      line-height: 25px;
      text-align: right;
      font-size: 12px;
      color: #303133;
      font-weight: 400;

      .cancel-btn {
        padding: 0 5px;
        margin: 0 5px;
        cursor: pointer;
      }
    }
  }
}
</style>
